import time
import cv2
import serial
from gomoku_vision import GomokuVision
from gomoku_ai import GomokuAI
from control_main import ChessRobot


class GomokuGame:
    def __init__(self, board_size=13):
        self.vision = GomokuVision(board_size=board_size)
        self.ai = GomokuAI(board_size=board_size)
        self.robot = ChessRobot()
        self.board_size = board_size
        self.current_player = 1  # 1=玩家, 2=AI
        self.player_piece = 1  # 1=黑棋, 2=白棋

        # 初始化串口
        self.serial_port = serial.Serial('/dev/ttyS9', 115200, timeout=1)
        time.sleep(2)  # 等待串口初始化

    def send_serial(self, message):
        """通过串口发送消息（仅保留特定的十六进制格式消息）"""
        # 定义消息到十六进制命令的映射
        hex_commands = {
            "AI_turn": bytes([0x65, 0x02, 0x01, 0x00, 0xFF, 0xFF, 0xFF]),
            "player_turn": bytes([0x65, 0x02, 0x02, 0x00, 0xFF, 0xFF, 0xFF]),
            "AI_win": bytes([0x65, 0x02, 0x03, 0x00, 0xFF, 0xFF, 0xFF]),
            "player_win": bytes([0x65, 0x02, 0x04, 0x00, 0xFF, 0xFF, 0xFF])
        }

        if message in hex_commands:
            # 发送十六进制命令
            hex_cmd = hex_commands[message]
            self.serial_port.write(hex_cmd)
            print(f"Sent hex command: {' '.join(f'{b:02X}' for b in hex_cmd)}")

    def read_serial(self):
        """从串口读取消息"""
        if self.serial_port.in_waiting > 0:
            message = self.serial_port.readline().decode().strip()
            print(f"Received from serial: {message}")
            return message
        return None

    def print_instructions(self):
        """打印操作说明"""
        print("\n操作说明:")
        print("1. 串口命令 'start' 开始/停止绘制网格")
        print("2. 串口命令 'detect' 检测玩家落子")
        print("3. 串口命令 'reset' 重置检测状态")
        print("4. 串口命令 'quit' 退出游戏")
        print("5. 玩家落子后，发送 'detect' 确认落子")

    def handle_serial_commands(self):
        """处理串口命令"""
        message = self.read_serial()
        if not message:
            return False

        if message == 'start':
            self.vision.toggle_grid()
            return True
        elif message == 'detect' and self.vision.grid_drawn:
            return True
        elif message == 'reset':
            self.vision.reset_detection()
            return True
        elif message == 'quit':
            return 'quit'

        return False

    def select_first_player_via_serial(self):
        """通过串口选择先手"""
        while True:
            message = self.read_serial()
            if message == '1':
                self.current_player = 1
                self.player_piece = 1
                self.vision.set_player_piece(1)
                self.send_serial("player_turn")
                return
            elif message == '2':
                self.current_player = 2
                self.player_piece = 2
                self.vision.set_player_piece(2)
                self.send_serial("AI_turn")
                return

    def select_difficulty_via_serial(self):
        """通过串口选择难度"""
        while True:
            message = self.read_serial()
            if message in ['1', '2', '3']:
                self.ai.difficulty = int(message)
                return

    def run(self):
        """运行游戏主循环"""
        # 初始化摄像头
        if not self.vision.init_camera():
            return

        # 通过串口选择先手和难度
        self.select_first_player_via_serial()
        self.select_difficulty_via_serial()

        # 主循环
        while not self.ai.game_over:
            ret, frame = self.vision.cap.read()
            if not ret:
                break

            # 水平翻转图像（镜像效果）
            frame = cv2.flip(frame, 1)

            # 显示当前帧
            display_frame = frame.copy()
            if self.vision.grid_drawn:
                display_frame = self.vision.draw_grid(display_frame)

            cv2.imshow("Go Board Detection", display_frame)

            # 处理串口命令
            serial_result = self.handle_serial_commands()
            if serial_result == 'quit':
                break

            # 处理键盘输入（保留原有功能）
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                break

            # 检测玩家落子（通过串口或键盘）
            if (serial_result or key == ord('d')) and self.vision.grid_drawn:
                if self.current_player == 1:  # 玩家回合
                    player_move, board_state = self.vision.detect_player_move(frame)

                    if player_move:
                        x, y = player_move
                        if self.ai.make_move(x, y, self.player_piece):
                            # 检查是否获胜
                            if self.ai.check_winner(x, y, self.player_piece):
                                self.send_serial("player_win")
                                self.ai.print_game_history()
                                break

                            self.current_player = 2  # 切换到AI回合
                            self.send_serial("AI_turn")
                        else:
                            pass
                    else:
                        pass

            # AI回合
            if self.current_player == 2 and not self.ai.game_over:
                time.sleep(1)  # 稍微延迟，模拟思考

                x, y = self.ai.get_ai_move()
                if x is not None and y is not None:
                    if self.ai.make_move(x, y, 2 if self.player_piece == 1 else 1):
                        # 调用机器人执行落子
                        command = self.ai.convert_to_robot_command(x, y, 2 if self.player_piece == 1 else 1)
                        self.robot.make_move(command)

                        # 标记该位置为已检测
                        if 0 <= x < self.board_size and 0 <= y < self.board_size:
                            self.vision.detected_cells[x][y] = True

                        # 检查是否获胜
                        if self.ai.check_winner(x, y, 2 if self.player_piece == 1 else 1):
                            self.send_serial("AI_win")
                            self.ai.print_game_history()
                            break

                        self.current_player = 1  # 切换到玩家回合
                        self.send_serial("player_turn")
                    else:
                        break
                else:
                    break

        # 游戏结束
        self.vision.release()
        self.serial_port.close()
        cv2.destroyAllWindows()


if __name__ == "__main__":
    game = GomokuGame(board_size=13)
    game.run()